package cn.org.farseer.sweetftp.rcp.ui;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TableColumn;

import cn.org.farseer.sweetftp.rcp.listener.FileDragListener;
import cn.org.farseer.sweetftp.rcp.listener.FileDropListener;

public class FileBrowser
{
	private TableViewer  viewer;

	private File currentDirectory;
	
	private String parentPath;
	
	private Display display;
	
	public FileBrowser(Composite parent) 
	{
		super();
		display = parent.getDisplay();
		buildListViewer(parent);
	}
	
	
	private void buildListViewer(Composite parent) 
	{
		viewer = new TableViewer(parent, SWT.BORDER|  SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		TableLayout layout = new TableLayout();   
		
		viewer.getControl().setSize(500, 500);
		
		layout.addColumnData(new ColumnWeightData(20));   
		new TableColumn(viewer.getTable(), SWT.BORDER | SWT.RIGHT).setText("");   
		
		layout.addColumnData(new ColumnWeightData(200));   
        new TableColumn(viewer.getTable(), SWT.BORDER).setText("名称");   
        
    	layout.addColumnData(new ColumnWeightData(200));   
        new TableColumn(viewer.getTable(), SWT.BORDER).setText("路径");   
		
        viewer.getTable().setLayout(layout);
        viewer.getTable().setLinesVisible(false);
        viewer.getTable().setHeaderVisible(true);
        final String userDir = System.getProperty("user.dir");
        
        viewer.getTable().setLayoutData(new RowData(500,500));
		viewer.setLabelProvider(new ITableLabelProvider() {

			public Image getColumnImage(Object element, int columnIndex)
			{
				switch(columnIndex)
				{
					case 0:
					{
						File file = (File) element;
						if(file.isDirectory())
						{
							try{
								return new Image(display,new FileInputStream(userDir + "\\img\\folder.gif"));
							}catch(Exception e){}
						}else
						{
							String fileName = file.getName();
							String extName = null;
							if(fileName.indexOf(".") != -1)
							{
								extName = fileName.substring(fileName.indexOf(".") + 1, fileName.length());
							}
							if(extName == null)
							{
								try{
									return new Image(display,new FileInputStream(userDir + "\\img\\file.gif"));
								}catch(Exception e){}
							}
							Program  program = Program.findProgram(extName);
							if(program == null)
							{
								try{
									return new Image(display,new FileInputStream(userDir + "\\img\\file.gif"));
								}catch(Exception e){}
							}
							return new Image(display,program.getImageData());
						}
					}
				}
				return null;
			}

			public String getColumnText(Object element, int columnIndex)
			{
				File file = (File) element;
				switch(columnIndex)
				{
					case 1:
					{
						if(file.getAbsolutePath().equals(parentPath))
							return "<上一层>";
						String name = file.getName();
						return name;
					}
					case 2:
					{
						return file.getAbsolutePath();
					}
				}
				return "";
			}

			public void addListener(ILabelProviderListener listener){}

			public void dispose(){}

			public boolean isLabelProperty(Object element, String property){return false;}

			public void removeListener(ILabelProviderListener listener){}
			
		});

		viewer.setContentProvider(new IStructuredContentProvider() 
		{
			
			
			public Object[] getElements(Object inputElement) 
			{
				File file = (File) inputElement;

				if (file.isDirectory()) 
				{
					File[] files = file.listFiles();
					File parent = file.getParentFile();
					if(parent != null)
					{
						parentPath = parent.getAbsolutePath();
						Object [] returnObjects = new Object[files.length + 1];
						returnObjects[0] = parent;
						for (int i = 1; i < returnObjects.length; i++)
						{
							returnObjects[i] = files[i-1];
						}
						return returnObjects;
					}else
						return files;
				}
				else 
					return new Object[] { file.getName()};
			}

			public void dispose() {}

			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
		});
		
		viewer.setSorter(new ViewerSorter() 
		{

			public int category(Object element) 
			{
				return ((File) element).isDirectory() ? 0 : 1;
			}

			public int compare(Viewer viewer, Object e1, Object e2) 
			{
				int cat1 = category(e1);
				int cat2 = category(e2);
				if (cat1 != cat2)
					return cat1 - cat2;
				return ((File) e1).getName().compareTo(((File) e2).getName());
			}
		});

		
				
		viewer.addDoubleClickListener(new IDoubleClickListener() 
		{
			public void doubleClick(DoubleClickEvent event) 
			{
				IStructuredSelection selection = (IStructuredSelection) event.getSelection();
				File clickFile = (File)selection.getFirstElement();
				if(clickFile.isDirectory())
					setCurrentDirectory(clickFile);
				else
				{
					try{
						Runtime.getRuntime().exec("cmd /c start " + clickFile.getAbsolutePath());
					}catch(Exception e){
						e.printStackTrace();
					}
				}
			}

		});
		
		viewer.addDropSupport(DND.Drop, new Transfer[]{FileTransfer.getInstance()}, new FileDropListener(this));
		
		
		viewer.addDragSupport(DND.DROP_COPY, new Transfer[]{FileTransfer.getInstance()}, new FileDragListener(this));
		
		final Menu menu = new Menu (parent.getShell(), SWT.POP_UP);
	    final MenuItem menuItem = new MenuItem (menu, SWT.PUSH);
	    menuItem.setText("复制");
	    final MenuItem delMenuItem = new MenuItem (menu, SWT.PUSH);
	    delMenuItem.setText("删除");
		viewer.getControl().setMenu(menu);
		menu.addMenuListener(new MenuAdapter() {
			
	        public void menuShown(MenuEvent e) {
	        	String fileNames[] = getSelectedFiles();
	            if (fileNames == null) {
	                menu.setVisible(false);
	                return;
	           }
	        }
	        
	    });

		menuItem.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e)
			{
				
			}

			public void widgetSelected(SelectionEvent e)
			{
				Clipboard clipboard = new Clipboard(e.display);
				String fileNames[] = getSelectedFiles();
				clipboard.setContents(new Object[]{fileNames}, new Transfer[]{FileTransfer.getInstance()});
				clipboard.dispose();
			}
			
		});
		
		delMenuItem.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e)
			{
				
			}

			public void widgetSelected(SelectionEvent e)
			{
				String fileNames[] = getSelectedFiles();
				if(fileNames != null)
				{
					for (int i = 0; i < fileNames.length; i++)
					{
						File delFile = new File(fileNames[i]);
						if(delFile.exists())
							delFile.delete();
					}
				}
				reflush();
			}
			
		});
		
		
		viewer.getControl().addKeyListener(new KeyListener(){

			public void keyPressed(KeyEvent e)
			{
				if ((e.stateMask & SWT.CTRL) != 0)
				{
						if(e.keyCode == 'c')
						{
							Clipboard clipboard = new Clipboard(e.display);
							String fileNames[] = getSelectedFiles();
							clipboard.setContents(new Object[]{fileNames}, new Transfer[]{FileTransfer.getInstance()});
							clipboard.dispose();
						}
						
						if(e.keyCode == 'v')
						{
							Clipboard clipboard = new Clipboard(e.display);
							Object obj = clipboard.getContents(FileTransfer.getInstance());
							if(obj != null)
							{
								String[] srcNames = (String[])obj;
								for (int i = 0; i < srcNames.length; i++)
								{
									File f = new File(srcNames[i]);
									if(f != null && f.exists())
									{
										File dir = (File)viewer.getInput();
										String destFilePath = dir.getAbsolutePath()  + File.separator + f.getName();
										try{
											if(f.isFile())
											{
												FileUtils.copyFile(f, new File(destFilePath));
											}else if(f.isDirectory())
											{
												FileUtils.copyDirectory(f, new File(destFilePath));
											}
										}catch(Exception e1)
										{
											e1.printStackTrace();
										}
									}
								}
							}
							clipboard.dispose();
							reflush();
						}
						
				}
			}

			public void keyReleased(KeyEvent e)
			{
				
			}
			
		});
		
		setCurrentDirectory(File.listRoots()[0]);
	}
	
	
	private void setCurrentDirectory(File directory) 
	{
		currentDirectory = directory;
		viewer.setInput(directory);
	}
	
	public void reflush()
	{
		viewer.refresh();
	}

	
	public String[] getSelectedFiles() 
	{
		IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
		List fileNameList = new LinkedList();
		Iterator iterator = selection.iterator();
		while (iterator.hasNext()) 
		{
			File file = (File) iterator.next();
			fileNameList.add(file.getAbsoluteFile().toString());
		}
		return (String[]) fileNameList.toArray(new String[fileNameList.size()]);
	}



	public void copyFiles(String[] sourceFileList) 
	{
		for (int i = 0; i < sourceFileList.length; i++) 
		{
			File sourceFile = new File(sourceFileList[i]);
			if (sourceFile.canRead() && currentDirectory.canWrite())
			{
				File destFile = new File(currentDirectory, sourceFile.getName());
				if (!destFile.exists()) 
				{
					FileOutputStream out;
					FileInputStream in;
					try {
						out = new FileOutputStream(destFile);
						in = new FileInputStream(sourceFile);
						byte[] buffer = new byte[1024];
						while ((in.read(buffer)) != -1) 
						{
							out.write(buffer);
						}
						out.flush();
						out.close();
						in.close();
						viewer.refresh();
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
			   }else {
				   	System.out.println( destFile +  " already exists, refusing to clobber");
			   }
			}else {
				System.out.println("Sorry, either your source file is not readable " + "or the target directory is not writable");
			}
		}
	}


}
